// 书籍服务，处理书源和API调用
import { setStore, getStore } from './book-store'
import { nanoid } from 'nanoid'
// 模拟书源列表
let bookSources = [];

// 获取所有书源
export const getBookSources = () => {
  // 从本地存储获取书源，如果有则使用本地存储的书源
  const localSources = getStore('bookSources');
  if (localSources && Array.isArray(localSources)) {
    bookSources = localSources;
  }
  return bookSources;
};
getBookSources()
// 添加书源
export const addBookSource = (source) => {
  // 如果是数组，则添加多个书源
  if (Array.isArray(source)) {
    // 过滤掉已存在的书源
    const newSources = source.filter(item => {
      return !bookSources.some(s => s.bookSourceUrl === item.bookSourceUrl);
    });
    if (newSources.length > 0) {
      bookSources = [...bookSources, ...newSources];
      setStore('bookSources', bookSources);
    }
    return newSources.length;
  } else {
    // 检查书源是否已存在
    const exists = bookSources.some(s => s.bookSourceUrl === source.bookSourceUrl);
    if (!exists) {
      bookSources = [...bookSources, source];
      setStore('bookSources', bookSources);
      return 1;
    }
    return 0;
  }
};

// 删除书源
export const deleteBookSource = (sourceUrl) => {
  const initialLength = bookSources.length;
  bookSources = bookSources.filter(s => s.bookSourceUrl !== sourceUrl);
  if (bookSources.length < initialLength) {
    setStore('bookSources', bookSources);
    return true;
  }
  return false;
};

// 获取文本内容，不包含子节点
const getTextWithoutChildren = (element) => {
  let content = ''
  // 克隆元素
  let clone = element.cloneNode(true);
  clone.childNodes.forEach(node=>{
    if(!['#text', 'BR'].some(item =>  item === node.nodeName)){
       node.remove();
    }
  })
  clone?.querySelectorAll('script, style').forEach(el => el.remove());
  clone?.childNodes.forEach(node=> (content = content + node.textContent + (isBlockTagName(node.nodeName) ? '\n' : '')));
  // 返回克隆元素的文本内容
  return content.trim();
}

// 判断元素是否为块级元素
const isBlockTagName = (tagName) => {
  const blockTags = [
    'ADDRESS', 'ARTICLE', 'ASIDE', 'BLOCKQUOTE', 'CANVAS', 'DD', 'DIV',
    'DL', 'DT', 'FIELDSET', 'FIGCAPTION', 'FIGURE', 'FOOTER', 'FORM',
    'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'HEADER', 'HR', 'LI', 'MAIN',
    'NAV', 'NOSCRIPT', 'OL', 'P', 'PRE', 'SECTION', 'TABLE', 'TFOOT',
    'UL', 'VIDEO', 'BR'
  ];
  return blockTags.includes(tagName.toUpperCase());
}

const replaceLocalUrls = (
  url,
  replacementHost = 'https://proxy.example.com'
) => {
  if (!url || url === 'javascript:void(0);') return '';

  const isFullUrl = /^([a-z]+:)?\/\//i.test(url);
  let path = '';

  // 判断是否是本地或内网地址
  const isLocalNetworkUrl = (urlString) => {
    try {
      const parsed = new URL(urlString);
      const hostname = parsed.hostname;

      return (
        hostname === 'localhost' ||
        hostname === '0.0.0.0' ||
        hostname === '127.0.0.1' ||
        /^10(\.\d{1,3}){3}$/.test(hostname) ||
        /^192\.168(\.\d{1,3}){2}$/.test(hostname) ||
        /^172\.(1[6-9]|2[0-9]|3[0-1])(\.\d{1,3}){2}$/.test(hostname)
      );
    } catch (e) {
      return false;
    }
  };

  if (isFullUrl) {
    if (url.startsWith('file://')) {
      // file:// 开头
      try {
        const urlObj = new URL(url);
        path = decodeURIComponent(urlObj.pathname || '/');
      } catch {
        return url;
      }
    } else if (isLocalNetworkUrl(url)) {
      // 内网地址处理
      try {
        const urlObj = new URL(url);
        path = urlObj.pathname || '/';
      } catch {
        return url;
      }
    } else {
      // 外部网址，跳过
      return url;
    }
  } else {
    // 是纯路径字符串
    path = decodeURIComponent(url);
  }

  // 标准化斜杠（Windows）
  path = path.replace(/\\/g, '/');

  // 去掉 Windows 盘符
  path = path.replace(/^\/?[a-zA-Z]:(.+asar)?/, '');

  // 去掉 macOS / Linux 典型系统目录前缀
  path = path.replace(/^\/?(Users|home|root|Desktop|Documents)\//i, '');

  // 保证 path 开头有 /
  if (!path.startsWith('/')) path = '/' + path;

  // 拼接为完整地址
  const result = replacementHost.replace(/\/+$/, '') + path;

  return result;
};

// 数组分块
const chunkArray = (arr, size) => {
  const result = [];
  for (let i = 0; i < arr.length; i += size) {
    let div = document.createElement('div');
    arr.slice(i, i + size).forEach(node=>div.appendChild(node))
    result.push(div);
  }
  return result;
}

// 规则解析，根据规则解析书籍信息
export const ruleAnalysis = (rule, doc, url) => {
  // 根据规则解析书籍信息
  if(!rule)return;
  let res;
  let rules = rule.split('@');
  // 保存 rules 获取到的内容
  let storage = [];
  
  for (let index = 0; index < rules.length; index++) {
    const rule = rules[index];
    let html = index ? storage[index - 1] : doc;
    let result

    

    // 获取元素 href 属性   /^src(?:\[(\w+)\])?$/
    let hrefRule = /^href(?:\[(\w+)\])?$/
    if(hrefRule.test(rule)){
      if(!html)return null;
      rule.replace(hrefRule, (str, p)=>{
        result = replaceLocalUrls(html.href, p ? url[p] : url.origin)
      })
    }

    // 获取元素文本
    if(/^text$/.test(rule)){
      if(!html)return null;
      // 因当前元素无渲染，innerText 与 textContent 效果一样， 需处理 script， style 以及换行符
      let content = ''
      if(Array.isArray(html)){
        html?.forEach(node=> (content = content + node.textContent + (isBlockTagName(node.nodeName) ? '\n' : '')));
        result = content.trim();
      }else{
        html?.querySelectorAll('script, style, br').forEach(el => el.remove());
        html?.childNodes.forEach(node=> (content = content + node.textContent + (isBlockTagName(node.nodeName) ? '\n' : '')));
        result = content.trim();
      }
      
    }

    // 获取元素内部 html
    if(/^html$/.test(rule)){
      if(!html)return null;
      result = html?.innerHTML;
    }

    // 获取元素 src 属性
    let srcRule =  /^src(?:\[(\w+)\])?$/
    if(srcRule.test(rule)){
      if(!html)return null;
      // 判断是否字符串
      if(typeof html === 'string'){
        rule.replace(srcRule, (str, p)=>{
          result = replaceLocalUrls(html, p ? url[p] : url.origin)
        })
      }else{
        rule.replace(srcRule, (str, p)=>{
          result = replaceLocalUrls(html.src, p ? url[p] : url.origin)
        })
      }
    }

    // 获取元素 value 属性
    if(/^value$/.test(rule)){
      if(!html)return null;
      result = html?.value
    }

    // 获取元素 data-[value] 自定义数据属性
    // let customizeRule = /^\[data\-([^\[\]]+)\]$/
    
    // if(customizeRule.test(rule)){
    //   console.log('????');
    //   let value = rule.replace(customizeRule, (str,p)=>p)
    //   result = html?.dataset[value]
    //   console.log('attribut',result);
    // }

    // 获取元素 属性 
    let attributeRule = /^\[([^\[\]]+)\]$/
    if(attributeRule.test(rule)){
      if(!html)return null;
      result = html?.getAttribute(rule.replace(attributeRule, (str,p)=>p))
    }

    // 获取元素内文本内容，不包含子节点
    if(/^textNodes$/.test(rule)){
      if(!html)return null;
      result = getTextWithoutChildren(html)
    }

    // 正则返回第一个参数
    let regexRule = /^\/(.+)\/$/
    if(regexRule.test(rule)){
      if(!html)return null;
      let str = regexRule.exec(rule)[1]
      let regex = new RegExp(str, 's');
      html.replace(regex, (regStr, p1)=>{
        result = p1.trim();
      })
    }



    // 执行模板 JS 脚本
    let scriptJsRule = /^\{\{([^\{\}]+)\}\}$/
    if(scriptJsRule.test(rule)){
      if(!html)return null;
      rule.replace(/^\{\{([^\{\}]+)\}\}$/, (regStr, p1)=>{
        let script = new Function('$','$html', p1);
        let value = script(html, doc.documentElement.outerHTML);
        result = value;
      })
    }

    // 获取元素内部子元素，可分割成组，也可对子元素进行 范围截取 以及选择
    let childRule = /^children(\|\d+)\[?(-?\d+)?:?(-?\d+)?\]$/
    
    if(childRule.test(rule)){
      if(!html?.children)return null;
      let children = [...html.children];
      rule.replace(childRule, (regStr, p1, p2, p3)=>{
        // let children = html.children;
        if(p1 && !p2 && !p3){
          result = chunkArray(children, parseInt(p1.slice(1)))
        }
        if(p1 && p2 && !p3){
          result = chunkArray(children, parseInt(p1.slice(1))).at(parseInt(p2))
        }
        if(p1 && p2 && p3){
          if(p3 === '0')result = chunkArray(children, parseInt(p1.slice(1))).slice(parseInt(p2));
          else result = chunkArray(children, parseInt(p1.slice(1))).slice(parseInt(p2), parseInt(p3));
        }
        if(!p1 && p2 && !p3){
          result = children.at(parseInt(p2))
        }
        if(!p1 && p2 && p3){
          result = children.slice(parseInt(p2), parseInt(p3));
        }
        if(!p1 && !p2 && p3){
          result = childen;
        }
      })
      
    }


    // 获取元素内部所有子元素集合（包括  文本节点），可对该集合进行 范围选取 以及 选择其中一个
    let childNodesRule = /^childNodes\[(-?\d+)?:?(-?\d+)?\]$/
    if(childNodesRule.test(rule)){
      if(!html?.childNodes)return null;
      rule.replace(childNodesRule, (regStr, p1, p2)=>{
        let childNodes = html.childNodes;
        if(!p1 && !p2){
          result = [...childNodes]
        }
        if(p1 && !p2){
          result = [...childNodes].at(parseInt(p1))
        }
        if(p1 && p2){
          if(p2 === '0')result = [...childNodes].slice(parseInt(p1));
          else result = [...childNodes].slice(parseInt(p1), parseInt(p2));
        }
      })
      
    }

    // 获取 id  class  tag 元素集合，可对该集合进行 范围选取 以及 选择其中一个
    let elementsRule = /^([\.#]?(?!children$)[^\[\]\{\}]+)\[(-?\d+)?:?(-?\d+)?\]$/
    
    if(elementsRule.test(rule) && !childNodesRule.test(rule) && !childRule.test(rule) && !srcRule.test(rule) && !hrefRule.test(rule)){
      if(!html)return null;
      rule.replace(elementsRule, (regStr, p1, p2, p3)=>{
        if(p1 && !p2 && !p3){
          result = [...html.querySelectorAll(p1)];
        }
        if(p1 && p2 && !p3){
          result = [...html.querySelectorAll(p1)].at(parseInt(p2))
        }
        if(p1 && p2 && p3){
          if(p3 === '0')result = [...html.querySelectorAll(p1)].slice(parseInt(p2));
          else result = [...html.querySelectorAll(p1)].slice(parseInt(p2), parseInt(p3));
        }
      })
    }

    // 通过 元素 type 属性获取元素
    let elementTypeRule = /^([\.#]?[^\[\]\{\}]+)\[type=(\w+)\]$/
    if(elementTypeRule.test(rule)){
      if(!html)return null;
      rule.replace(elementTypeRule, (str, p1, p2)=>{
        result = html.querySelector(str)
      })
    }

    // 获取元素
    let elementRule = /^([\.#]?[^\/\[\]\{\}]+)$/
    if(elementRule.test(rule) &&  !['text', 'html', 'src', 'href', 'value', 'textNodes'].some(item=>item === rule) && !srcRule.test(rule) && !hrefRule.test(rule)){
      if(!html)return null;
      rule.replace(elementRule, (str)=>{
        result = html.querySelector(str)
        
      })


    }

    storage.push(result)
    
    if(index === rules.length - 1){
      res = storage[index]
      
    }

  }
  return res
}



// const getBookList = async (bookSource) => {
//   await getBookList()
// }


// 本地书籍分析章节，内容
export const getBookDetailsAndChapters = async (book) => {
  let chapters = [],contents = [], offset = 0, content = book.content;
  let reg = /(\s第[零一二三四五六七八九十百千万\d]{0,}卷\s[^\n]{0,})?\s第[零一二三四五六七八九十百千万、\d]{0,}[章回节]\s[^\n]{0,}\n/
  let regAll = /(\s第[零一二三四五六七八九十百千万\d]{0,}卷\s[^\n]{0,})?\s第[零一二三四五六七八九十百千万、\d]{0,}[章回节]\s[^\n]{0,}\n/g
  // 解析开始是否章节
  if(!/^\s第[零一二三四五六七八九十百千万\d]{0,}[章回节][^\n]{0,}\n/.test(content)){
    // 获取第一行作为 目录标题
    let firstLine = content.match(/^([^\n]+)\n/)[1];
    let chaptersTitle = firstLine.trim();
    chapters.push({ title: chaptersTitle, url: '', id: 0, length: firstLine.length, cache: true});
    offset = firstLine.length;
    content.replace(reg,(str, placeholder, index)=>{
      let chapterContent = content.slice(offset, index);
      // 去除开始的换行
      chapterContent = chapterContent.replace(/^\n+/,'')
      contents.push({ title: chaptersTitle, content: chapterContent, id: 0, length: chapterContent.length,});
      offset = index;
    })
  }

  content.replace(regAll,(str , placeholder , index)=>{
    // console.log(chapterConten, index);

    if(offset !== index){
      contents.push({
        id: offset,
        content: content.slice(offset + (chapters.at(-1)?.length || 0), index).trim(),
        title: chapters.at(-1)?.title
      })
    };
    let chapterTitle = str.trim();
    chapters.push({title: chapterTitle, url: '', id: index, length: str.length , cache: true});
    offset = index;
    return str;
  });
  contents.push({
    id: offset,
    content: content.slice(offset + (chapters.at(-1)?.length || 0)),
    title: chapters.at(-1)?.title
  })
  return {
    chapters: chapters,
    contents: contents
  }
}

// 默认阅读设置
const defaultReadingSettings = {
  themes: [
    {
      id: 'default',
      name: '默认主题',
      backgroundColor: '#f8f4e9',
      color: '#333333',
      fontSize: 18,
      lineHeight: 1.8,
      letterSpacing: 0.5,
      fontFamily: ''
    },
    {
      id: 'night',
      name: '夜间模式',
      backgroundColor: '#1a1a1a',
      color: '#dddddd',
      fontSize: 18,
      lineHeight: 1.8,
      letterSpacing: 0.5,
      fontFamily: ''
    },
    {
      id: 'paper',
      name: '纸张',
      backgroundColor: '#f0e6d2',
      color: '#5c4b36',
      fontSize: 18,
      lineHeight: 1.8,
      letterSpacing: 0.5,
      fontFamily: ''
    },
    {
      id: 'ivory',
      name: '米白纸质',
      backgroundColor: '#fdfaf6',
      color: '#3b3b3b',
      fontSize: 18,
      lineHeight: 1.8,
      letterSpacing: 0.5,
      fontFamily: ''
    },
    {
      id: 'green-soft',
      name: '淡绿色护眼',
      backgroundColor: '#eef5db',
      color: '#2f2f2f',
      fontSize: 18,
      lineHeight: 1.8,
      letterSpacing: 0.5,
      fontFamily: ''
    },
    {
      id: 'warm-night',
      name: '暖夜墨棕',
      backgroundColor: '#2c2b29',
      color: '#e3dac9',
      fontSize: 18,
      lineHeight: 1.8,
      letterSpacing: 0.5,
      fontFamily: ''
    },
    {
      id: 'gray-minimal',
      name: '极简冷灰',
      backgroundColor: '#f0f2f5',
      color: '#222222',
      fontSize: 18,
      lineHeight: 1.8,
      letterSpacing: 0.5,
      fontFamily: ''
    },
    {
      id: 'japan-soft',
      name: '日系淡雅',
      backgroundColor: '#fbf8f1',
      color: '#4a4a4a',
      fontSize: 18,
      lineHeight: 1.8,
      letterSpacing: 0.5,
      fontFamily: ''
    },
    {
      id: 'pink-milk',
      name: '草莓牛奶',
      backgroundColor: '#fff1f5', // 淡粉色
      color: '#5c375c',           // 樱桃紫
      fontSize: 18,
      lineHeight: 1.8,
      letterSpacing: 0.5,
      fontFamily: '"ZCOOL KuaiLe", "Comic Sans MS", cursive'
    },
    {
      id: 'mint-choco',
      name: '薄荷巧克力',
      backgroundColor: '#e6f9f0', // 薄荷绿
      color: '#4b3832',           // 巧克力棕
      fontSize: 18,
      lineHeight: 1.8,
      letterSpacing: 0.5,
      fontFamily: '"Baloo 2", "幼圆", sans-serif'
    },
    {
      id: 'sky-sugar',
      name: '蓝天棉花糖',
      backgroundColor: '#eef6ff', // 天空蓝白
      color: '#364f6b',           // 深蓝灰
      fontSize: 18,
      lineHeight: 1.8,
      letterSpacing: 0.5,
      fontFamily: '"Quicksand", "Noto Sans SC", sans-serif'
    },
    {
      id: 'lemon-cream',
      name: '柠檬奶油',
      backgroundColor: '#fffce0', // 奶油黄
      color: '#6a4e36',           // 棕橘
      fontSize: 18,
      lineHeight: 1.8,
      letterSpacing: 0.5,
      fontFamily: '"Ma Shan Zheng", "LXGW WenKai", cursive'
    }
  ],
  currentThemeId: 'default'
};

// 默认语音设置
const defaultVoiceSettings = {
  rate: 1.0,  // 语速，范围0.1-10
  pitch: 1.0, // 音调，范围0.5-2.0
  voiceName: '', // 语音名称，空字符串表示使用默认语音
  volume: 1.0  // 音量，范围0-1.0
};

// 默认下载设置
let defaultPath =  window.utools && window.utools.getPath('downloads') || ''
const defaultDownloadSettings = {
  savePath: defaultPath,
  maxConcurrent: 3, // 最大并发下载数
  autoRetry: true,  // 自动重试
  retryCount: 3,    // 重试次数
  // contentFilter: {   // 内容过滤
  //   removeAds: true,  // 移除广告
  //   cleanFormatting: true, // 清理格式
  //   filterKeywords: ['广告', '本章未完', '请关注'] // 过滤关键词
  // },
  riskControl: {
    enableRateLimit: true, // 启用请求频率限制
    requestInterval: 1000,  // 请求间隔（毫秒）
    // maxRequestsPerMinute: 30 // 每分钟最大请求数
  }
};

// 获取阅读设置
export const getReadingSettings = () => {
  if (window.utools) {
    const savedSettings = getStore('reading-settings');
    return savedSettings || defaultReadingSettings;
  }
  return defaultReadingSettings;
};

// 保存阅读设置
export const saveReadingSettings = (settings) => {
  // if (window.utools) {
  //   window.utools.dbStorage.setItem('reading-settings', settings);
  // }
  setStore('reading-settings', settings)
  return settings;
};

// 获取语音设置
export const getVoiceSettings = () => {
  if (window.utools) {
    const savedSettings = getStore('voice-settings');
    return savedSettings || defaultVoiceSettings;
  }
  return defaultVoiceSettings;
};

// 保存语音设置
export const saveVoiceSettings = (settings) => {
  // if (window.utools) {
  //   window.utools.dbStorage.setItem('voice-settings', settings);
  // }
  setStore('voice-settings', settings)
  return settings;
};

// 获取下载设置
export const getDownloadSettings = () => {
  if (window.utools) {
    const savedSettings = getStore('download-settings');
    return savedSettings || defaultDownloadSettings;
  }
  return defaultDownloadSettings;
};

// 保存下载设置
export const saveDownloadSettings = (settings) => {
  // if (window.utools) {
  //   window.utools.dbStorage.setItem('download-settings', settings);
  // }
  setStore('download-settings', settings)
  return settings;
};

// 创建新主题
export const createTheme = (theme) => {
  const settings = getReadingSettings();
  const newTheme = {
    id: `theme_${nanoid()}`,
    ...theme
  };
  settings.themes.push(newTheme);
  saveReadingSettings(settings);
  return newTheme;
};

// 删除主题
export const deleteTheme = (themeId) => {
  const settings = getReadingSettings();
  // 不允许删除当前使用的主题
  if (settings.currentThemeId === themeId) {
    return false;
  }
  const index = settings.themes.findIndex(t => t.id === themeId);
  if (index !== -1) {
    settings.themes.splice(index, 1);
    saveReadingSettings(settings);
    return true;
  }
  return false;
};

// 应用主题
export const applyTheme = (themeId) => {
  const settings = getReadingSettings();
  const theme = settings.themes.find(t => t.id === themeId);
  if (theme) {
    settings.currentThemeId = themeId;
    saveReadingSettings(settings);
    return theme;
  }
  return null;
};

// 获取当前主题
export const getCurrentTheme = () => {
  const settings = getReadingSettings();
  return settings.themes.find(t => t.id === settings.currentThemeId) || settings.themes[0];
};

export const request = async (url,option) => {
  let timeout = 30000;
  const controller = new AbortController();
  const signal = controller.signal;
  const id = setTimeout(() => controller.abort(), timeout);
  try {
    let html;
    let res = await fetch(url, {
      ...option,
      signal
    });
    if (res.status >= 200 && res.status < 300) {
      let type = res.headers.get('content-type');
      if(/gbk/.test(type)){
        let buffer = await res.arrayBuffer();
        html = new TextDecoder('gbk').decode(buffer);
      }else{
        html = await res.text();
      }
      clearTimeout(id);
      return {
        html,
        url: new URL(res.url)
      };
    }else{
      throw new Error('请求失败')
    }
  } catch (error) {
    if(error.name === 'AbortError'){
      return {
        html: '',
        url: url
      }
    }
  }
}



// 获取当前书籍书源规则信息
export const getBookSourceRule = (book) => {
  return bookSources.find(item => item.bookSourceUrl === book.source);
};

// 获取书籍详情
export const getBookDetails = async (book, bookSourceRule) => {
  try {
      let {url, html} = await request(book.url);
      let parser = new DOMParser();
      let doc = parser.parseFromString(html, 'text/html');
      
      let bookInfo = {};
      for(let key in bookSourceRule.ruleBookInfo){
        if(!bookSourceRule.ruleBookInfo[key]){bookInfo[key] = ''; continue;}
        let value = ruleAnalysis(bookSourceRule.ruleBookInfo[key], doc, url);
        bookInfo[key] = value;
      }
      
      return {
        book: book,
        info: {
          ...bookInfo,
          doc,
          url
        },
        rule: bookSourceRule.ruleToc
      };
  } catch (error) {
    throw new Error(error)
  }
}


// 获取书籍目录
export const getBookChapters = async (param, all = true, length = 0) => {
  let bool = param.info?.tocUrl;
  let doc, url;
  if(bool){
    try {
      let { url : u , html} = await request(param.info?.tocUrl);
      url = u;
      let parser = new DOMParser();
      doc = parser.parseFromString(html, 'text/html');
    } catch (error) {
      throw new Error(error)
    }
  }else{
    doc = param.info.doc;
    url = param.info.url;
  }
  let list = ruleAnalysis(param.rule.chapterList, doc, url);
 
  let nextTocUrl = ruleAnalysis(param.rule.nextTocUrl, doc, url);
  let chapters = list.map((item, index)=>{
    return {
      id: index + length,
      title: ruleAnalysis(param.rule.chapterName, item, url),
      url: ruleAnalysis(param.rule.chapterUrl, item, url),
    }
  });

  if(!all)return chapters
  if(!nextTocUrl)return chapters

  try{
    let nextChapters = await getBookChapters({
      ...param,
      info: {
        ...param.info,
        tocUrl: nextTocUrl
      }
    }, true, length + chapters.length)
    return [...chapters, ...nextChapters]
  }catch(e){
    return []
  }
}


// 获取章节内容
export const getChapterContent = async (url, bookSourceRule) => {
  let contentInfo = {
    content: '',
    nextPageUrl: url
  };
  while(contentInfo?.nextPageUrl){
    try {
      let { url: u, html } = await request(contentInfo.nextPageUrl);
      let parser = new DOMParser()
      let doc = parser.parseFromString(html, 'text/html')  
      if(!doc.querySelector('body').innerText){
        throw new Error('本章章节出现错误')
      }
      for(let key in bookSourceRule.ruleContent){
        if(!bookSourceRule.ruleContent[key]){contentInfo[key] = ''; continue;}
        let value = ruleAnalysis(bookSourceRule.ruleContent[key], doc , u);
        if(Array.isArray(value)){
          let content = ''
          value.forEach((item)=>{
            content = content + item.textContent +  '\n'
          })
          value = content
        }
        if(key === 'content'){
          contentInfo.content = contentInfo.content + value;
          continue;
        }
        contentInfo[key] = value;
      }
      let reg = new RegExp(contentInfo.title.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g')
      contentInfo.content = contentInfo.content.replace(reg, '').trim();
      if(!bookSourceRule.ruleContent?.nextPageUrl)contentInfo.nextPageUrl = '';
    } catch (error) {
      console.log(error);
      throw new Error('本章章节出现错误')
    }
  }

  return contentInfo;
};


// 保存书籍
export const saveBook = async (contentFilter, book) => {
  let config = getDownloadSettings();
  let content = '';
  for (let index = 0; index < contentFilter.length; index++) {
    const element = contentFilter[index];
    const chapter = element?.title + '\n\n' + element?.content + '\n\n'
    content += chapter;
  }
  try {
    let path = await window.services.writeTextFile(content,  window.services.pathJoin(config.savePath, `${book.title}.txt`))
    return path
  } catch (error) {
    throw new Error(error);
  }
};


// 听书
export class SynthesisSpeech extends EventTarget {
  constructor(data) {
    super();
    this.speech = window.speechSynthesis
    this.utterance = new SpeechSynthesisUtterance()
    // 文本选取
    this.range = document.createRange();
    // 语音配置
    this.voiceConfig = null;
    // 当前阅读段落索引
    this.count = 0;
    // 当前章节每一段内容
    this.excerpts = null;
    // 章节内容元素用于高亮文本
    this.contentElement = null;
    // 高亮标记
    this.highlightElement = null;
    // 播放状态
    this.isPlaying = 0;
    // 回话进度
    this.sentenceText = data.sentenceText;
    console.log(data.sentenceText);
    
    this.getHighlightTheme()
    this.speechConfig()
    this.readerPlaying = data.setIsPlaying
    this.upProgress = data.upProgress
    this.listenSpeakEnd()
  }

  getHighlightTheme() {
    let theme = getCurrentTheme();
    let color = theme.color;
    let backgroundColor = theme.backgroundColor;
    this.theme = {
      color,
      backgroundColor
    }
  }

  speechConfig(config){
    if(config){
      this.voiceConfig = config;
    }else{
      this.voiceConfig = getVoiceSettings();
    }

    this.utterance.rate = this.voiceConfig.rate;
    this.utterance.pitch = this.voiceConfig.pitch;
    this.utterance.volume = this.voiceConfig.volume;
    this.utterance.voice = this.speech.getVoices().find(voice => voice.name === this.voiceConfig.voiceName) ;
  }

  // setCount(value){
  //   this.count = value;
  // }

  // 分析章节内容
  analysisContent(el){
    let content = el.textContent;
    const regex = /(?:(?:“[^“”]*”|‘[^‘’]*’|\S+)(?:[。！？?!,:：“”‘’、—…\n()]*|$))/g;
    const results = [];
    let match;
  
    while ((match = regex.exec(content)) !== null) {
      results.push({
        node: el,
        text: match[0],     // 句子文本
        start: match.index, // 句子起始位置
        end: match.index + match[0].length // 句子结束位置
      });
    }

    return results;
  }

  // 创建说话内容上下文
  createContentContext(el){
    this.stop();
    this.contentElement = el;
    
    let titleExcerpt = {
      node: el.querySelector('.chapter-title'),
      text: el.querySelector('.chapter-title').innerText,
      start: 0,
      end: el.querySelector('.chapter-title').innerText.length
    }
    this.excerpts = [
      titleExcerpt,
      ...this.analysisContent(el.querySelector('.content-text'))
    ];
    this.contentElement = el;
    let current = this.excerpts.findIndex(item=> item.text === this.sentenceText);
    console.log(current);
    
    if(current > -1)this.count = current;
    if(this.isPlaying === 1)this.speak();
  }

  // 高亮说话内容
  highlight() {
    this.clearHighlight()
    let current = this.excerpts[this.count];
    // console.log(this.contentElement.childNodes[0]);
    this.range.setStart(current.node.childNodes[0], current.start)
    this.range.setEnd(current.node.childNodes[0], current.end)
    let span = document.createElement('span')
    span.style.backgroundColor = this.theme.color
    span.style.color = this.theme.backgroundColor
    span.style.borderRadius = '3px'
    this.range.surroundContents(span)
    this.range.collapse(false)
    this.highlightElement = span;
    let rect = this.highlightElement.getBoundingClientRect();
    let viewportHeight = window.innerHeight;
    if (rect.top < 0 || rect.bottom > viewportHeight) {
      this.contentElement.scrollTop = this.highlightElement.offsetTop - this.contentElement.offsetHeight / 2;
    }
  }

  // 清除高亮内容
  clearHighlight(){
    if(!this.highlightElement)return;
    let text = this.highlightElement.innerText;
    this.range.selectNode(this.highlightElement)
    this.range.deleteContents()
    let textNode = document.createTextNode(text)
    this.range.insertNode(textNode)
    if (textNode.previousSibling && textNode.previousSibling.nodeType === Node.TEXT_NODE) {
      textNode.nodeValue = textNode.previousSibling.nodeValue + textNode.nodeValue;
      textNode.previousSibling.remove();
    }
    if (textNode.nextSibling && textNode.nextSibling.nodeType === Node.TEXT_NODE) {
      textNode.nodeValue = textNode.nodeValue + textNode.nextSibling.nodeValue;
      textNode.nextSibling.remove();
    }
    this.range.collapse()
    this.highlightElement = null;
  }

  speak(){
    this.speech.cancel()
    this.upProgress(this.excerpts[this.count].text)
    this.utterance.text = this.excerpts[this.count].text;
    this.speech.speak(this.utterance)
    this.highlight()
    if(this.isPlaying === 2){
      this.pause()
    }
  }

  // 暂停
  pause(){  
    if(this.speech.speaking && this.speech.paused){
      this.setPlaying(1)
      this.speech.resume()
    }
    if(this.speech.speaking && !this.speech.paused){
      this.setPlaying(2)
      this.speech.pause()
    }
    if(!this.speech.speaking){
      this.setPlaying(1)
      this.speak()
    }
  }

  dispatch(type){
    this.dispatchEvent(new CustomEvent('change', {
      detail: {
        type,
        count: this.count,
        total: this.excerpts.length
      }
    }))
  }

  // 监听说话结束
  listenSpeakEnd(){
    this.utterance.onend = () => {
      // 防止在语音暂停后结束时间触发 需对 count 进行处理 
      if(this.isPlaying === 2){
        if(this.highlightElement)this.count++;
        if(this.excerpts && this.count >= this.excerpts.length){
          this.dispatch('end')
        }
        return
      };
      this.count++;
      if(!this.excerpts || this.excerpts.length === 0)return
      if(this.count >= this.excerpts.length){
        this.dispatch('end')
        return;
      }
      this.speak()
    }
  }
  // 上一段
  prev(){
    this.speech.cancel()
    this.count--;
    if(this.count < 0){
      this.dispatch('end')
      return;
    }
    this.speak()
  }

  // 下一段
  next(){
    this.speech.cancel()
    this.count++;
    if(this.count >= this.excerpts.length){
      this.dispatch('end')
      return;
    }
    this.speak()
  }

  // 停止
  stop(){
    this.speech.cancel()
    this.utterance.text = '';
    this.count = 0;
    this.contentElement = null;
    this.excerpts = null;
    this.clearHighlight()
    // this.dispatch('stop')
  }

  // 设置播放状态
  setPlaying(isPlaying){
    this.readerPlaying(isPlaying)
    this.isPlaying = isPlaying;
  }
}
